package com.ljb.haikanglibrary;

import android.content.Context;
import android.net.wifi.WifiManager;
import android.view.SurfaceView;

import com.hik.mcrsdk.MCRSDK;
import com.hik.mcrsdk.rtsp.RtspClient;
import com.hikvision.vmsnetsdk.CameraInfo;
import com.hikvision.vmsnetsdk.ControlUnitInfo;
import com.hikvision.vmsnetsdk.DeviceInfo;
import com.hikvision.vmsnetsdk.LineInfo;
import com.hikvision.vmsnetsdk.RealPlayURL;
import com.hikvision.vmsnetsdk.RegionInfo;
import com.hikvision.vmsnetsdk.ServInfo;
import com.hikvision.vmsnetsdk.VMSNetSDK;
import com.ljb.haikanglibrary.callbacks.MsgCallback;
import com.ljb.haikanglibrary.callbacks.MsgIds;
import com.ljb.haikanglibrary.live.ConstantLive;
import com.ljb.haikanglibrary.live.LiveCallBack;
import com.ljb.haikanglibrary.live.LiveControl;
import com.ljb.haikanglibrary.utils.JsonKit;
import com.ljb.haikanglibrary.utils.L;

import java.util.ArrayList;
import java.util.List;


/**
 * 海康威视,sdk工具类
 * Created by ljb on 2017/5/25.
 */

public class HaiKangManager {

    private static HaiKangManager m;
    /**
     * 服务器地址
     */
    private String servAddr;
    /**
     * 服务器信息
     */
    private ServInfo servInfo;

    private HaiKangManager() {
    }

    /**
     * 获取管理器的对象
     *
     * @return
     */
    public static HaiKangManager init() {
        if (m == null) {
            m = new HaiKangManager();
        }
        return m;
    }

    /**
     * 初始化SDK,需在Application中进行初始化
     */
    public void initSDK() {
        MCRSDK.init();
        RtspClient.initLib();
        MCRSDK.setPrint(1, null);
    }


    /**
     * 获取登录设备mac地址
     */
    public String getMac(Context c) {
        WifiManager wm = (WifiManager) c.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
        String mac = wm.getConnectionInfo().getMacAddress();
        return mac == null ? "" : mac;
    }

    /**
     * 错误描述
     *
     * @return
     */
    private String errDesc() {
        return "errorDesc:" + VMSNetSDK.getInstance().getLastErrorDesc() + ",errorCode:" + VMSNetSDK.getInstance().getLastErrorCode();
    }

    /**
     * 获取线路
     *
     * @param servAddr 服务器地址
     * @return 该服务器地址的线路信息集合
     */
    public List<LineInfo> fetchLines(String servAddr) {
        this.servAddr = servAddr;
        List<LineInfo> lineInfoList = new ArrayList<>();
        boolean ret = VMSNetSDK.getInstance().getLineList(servAddr, lineInfoList);
        if (ret) {
            L.e("获取线路成功:" + JsonKit.toJson(lineInfoList));
        } else {
            L.e("获取线路失败" + errDesc());
        }
        return lineInfoList;
    }

    /**
     * 登录视频服务器
     *
     * @param userName 登录名
     * @param passWord 登录密码
     * @param lineInfo 线路信息
     * @param macAddr  本机mac地址
     * @return 指定线路的服务器信息
     */
    public ServInfo loginServ(String userName, String passWord, LineInfo lineInfo, String macAddr) {
        servInfo = new ServInfo();
        boolean ret = VMSNetSDK.getInstance().login(servAddr, userName, passWord, lineInfo.lineID, macAddr, servInfo);
        if (ret) {
            L.e("登录视频服务器" + lineInfo.lineName + "成功: " + JsonKit.toJson(servInfo));
        } else {
            L.e("登录视频服务器失败" + errDesc());
        }
        return servInfo;
    }

    /**
     * 获取控制中心列表
     *
     * @param callback 回调
     */
    public void requestCtrlUnitList(MsgCallback callback) {
        String sessionID = servInfo.sessionID;
        int controlUnitID = 0;// 首次获取数据，表示根目录
        int numPerPage = 10000;// 此处传10000，由于实际不可能有那么多，表示获取所有数据
        int curPage = 1;
        List<ControlUnitInfo> ctrlUnitList = new ArrayList<>();

        // 获取控制中心列表
        boolean ret = VMSNetSDK.getInstance().getControlUnitList(servAddr, sessionID, controlUnitID, numPerPage, curPage, ctrlUnitList);
        if (ret) {
            L.e("获取控制中心列表成功" + JsonKit.toJson(ctrlUnitList));
        } else {
            L.e("获取控制中心列表失败" + errDesc());
        }
        if (callback != null) {
            callback.onMsg(ret ? MsgIds.GET_C_F_NONE_SUC : MsgIds.GET_C_F_NONE_FAIL, ctrlUnitList);
        }
    }

    /**
     * 从控制中心获取下级资源列表
     *
     * @param controlUnitID 控制中心id
     * @param callback      回调
     */
    public void requestSubResFromCtrlUnit(int controlUnitID, MsgCallback callback) {
        boolean responseFlag;

        String sessionID = servInfo.sessionID;
        int numPerPage = 10000;// 此处取10000，表示每页获取的数量，这个数值可以根据实际情况进行修改
        int curPage = 1;// 当前获取的数据是第几页

        // 1.从控制中心获取控制中心
        List<ControlUnitInfo> ctrlUnitList = new ArrayList<>();
        boolean ret = VMSNetSDK.getInstance().getControlUnitList(servAddr, sessionID, controlUnitID, numPerPage, curPage, ctrlUnitList);
        if (ret) {
            L.e("从控制中心获取控制中心成功" + JsonKit.toJson(ctrlUnitList));
        } else {
            L.e("从控制中心获取控制中心失败" + errDesc());
        }
        responseFlag = ret;

        // 2.从控制中心获取区域列表
        List<RegionInfo> regionList = new ArrayList<>();
        ret = VMSNetSDK.getInstance().getRegionListFromCtrlUnit(servAddr, sessionID, controlUnitID, numPerPage, curPage, regionList);
        if (ret) {
            L.e("从控制中心获取区域列表成功" + JsonKit.toJson(regionList));
        } else {
            L.e("从控制中心获取区域列表失败" + errDesc());
        }
        responseFlag = ret || responseFlag;


        // 3.从控制中心获取摄像头列表
        List<CameraInfo> cameraList = new ArrayList<>();
        ret = VMSNetSDK.getInstance().getCameraListFromCtrlUnit(servAddr, sessionID, controlUnitID, numPerPage, curPage, cameraList);
        if (ret) {
            L.e("从控制中心获取摄像头列表成功" + JsonKit.toJson(cameraList));
        } else {
            L.e("从控制中心获取摄像头列表失败" + errDesc());
        }
        responseFlag = ret || responseFlag;

        List<Object> allData = new ArrayList<>();
        allData.addAll(ctrlUnitList);
        allData.addAll(regionList);
        allData.addAll(cameraList);

        if (callback != null) {
            callback.onMsg(responseFlag ? MsgIds.GET_SUB_F_C_SUC : MsgIds.GET_SUB_F_C_FAIL, allData);
        }
    }

    /**
     * 从区域获取下级资源列表
     *
     * @param regionID 区域id
     * @param callback 回调
     */
    public void requestSubResFromRegion(int regionID, MsgCallback callback) {
        boolean responseFlag;

        String sessionID = servInfo.sessionID;
        int numPerPage = 10000;
        int curPage = 1;

        // 1.从区域获取区域列表
        List<RegionInfo> regionList = new ArrayList<>();
        boolean ret = VMSNetSDK.getInstance().getRegionListFromRegion(servAddr, sessionID, regionID, numPerPage, curPage, regionList);
        if (ret) {
            L.e("从区域获取区域列表成功" + JsonKit.toJson(regionList));
        } else {
            L.e("从区域获取区域列表失败" + errDesc());
        }
        responseFlag = ret;

        // 2.从区域获取监控点（摄像头）列表
        List<CameraInfo> cameraList = new ArrayList<>();
        ret = VMSNetSDK.getInstance().getCameraListFromRegion(servAddr, sessionID, regionID, numPerPage, curPage, cameraList);
        if (ret) {
            L.e("从区域获取区域监控点成功" + JsonKit.toJson(cameraList));
        } else {
            L.e("从区域获取区域监控点失败" + errDesc());
        }
        responseFlag = responseFlag || ret;


        List<Object> allData = new ArrayList<>();
        allData.addAll(regionList);
        allData.addAll(cameraList);

        if (callback != null) {
            callback.onMsg(responseFlag ? MsgIds.GET_SUB_F_R_SUC : MsgIds.GET_SUB_F_R_FAILED, allData);
        }
    }

    private LiveCallBack callBack;

    /**
     * 获取监控设备连接信息
     *
     * @param cameraInfo
     * @param callBack
     * @return
     */
    public ControlModel requestDeviceInfo(CameraInfo cameraInfo, LiveCallBack callBack) {
        this.callBack = callBack;
        LiveControl liveControl = new LiveControl();
        liveControl.setLiveCallBack(callBack);
        DeviceInfo deviceInfo = new DeviceInfo();

        return new ControlModel(liveControl, cameraInfo, deviceInfo.userName, deviceInfo.password);
    }

    /**
     * 启动预览
     *
     * @param controlModel
     * @param streamType   取流方式:2表示MAG取流方式,1表示子流码取流方式
     * @param surfaceView
     */
    public void startLive(ControlModel controlModel, int streamType, SurfaceView surfaceView) {
        LiveControl liveControl = controlModel.liveControl;
        String playUrl = getPlayUrl(controlModel, streamType);
        if (playUrl.isEmpty()) {
            return;
        }
        liveControl.setLiveParams(playUrl, controlModel.userName, controlModel.password);
        if (liveControl.LIVE_PLAY == liveControl.getLiveState()) {
            liveControl.stop();
        }

        if (liveControl.LIVE_INIT == liveControl.getLiveState()) {
            liveControl.startLive(surfaceView);
        }
    }

    /**
     * 停止预览
     */
    public void stopLive(ControlModel controlModel) {
        LiveControl liveControl = controlModel.liveControl;
        if (liveControl != null) {
            liveControl.stop();
        }
    }

    /**
     * 获取设备播放地址
     *
     * @param controlModel
     * @param streamType   取流方式:2表示MAG取流方式,1表示子流码取流方式
     * @return
     */
    private String getPlayUrl(ControlModel controlModel, int streamType) {
        RealPlayURL realPlayURL = new RealPlayURL();
        boolean ret = VMSNetSDK.getInstance().getRealPlayURL(servAddr, servInfo.sessionID, controlModel.cameraInfo.cameraID, streamType, realPlayURL);
        if (ret) {
            callBack.onMessageCallback(ConstantLive.GET_PLAYURL_SUCESS);
            L.e("获取播放地址成功" + JsonKit.toJson(realPlayURL));
        } else {
            callBack.onMessageCallback(ConstantLive.GET_PLAYURL_ERROR);
            L.e("获取播放地址失败" + errDesc());
            return "";
        }

        DeviceInfo deviceInfo = new DeviceInfo();
        ret = VMSNetSDK.getInstance().getDeviceInfo(servAddr, servInfo.sessionID, controlModel.cameraInfo.deviceID, deviceInfo);
        if (ret) {
            L.e("获取监控点设备信息成功" + JsonKit.toJson(deviceInfo));
            controlModel.userName = deviceInfo.userName;
            controlModel.password = deviceInfo.password;
        } else {
            L.e("获取监控点设备信息失败" + errDesc());
        }

        if (streamType == 2) {
            return realPlayURL.url2;
        } else {
            return realPlayURL.url1;
        }
    }

    /**
     * 显示信息
     *
     * @param message
     */
    public void showMessage(int message) {
        switch (message) {
            case ConstantLive.RTSP_SUCCESS:
                L.e("启动取流成功");
                break;
            case ConstantLive.STOP_SUCCESS:
                L.e("停止成功");
                break;
            case ConstantLive.START_OPEN_FAILED:
                L.e("开启播放库失败");
                break;
            case ConstantLive.PLAY_DISPLAY_SUCCESS:
                L.e("播放成功");
                break;
            case ConstantLive.RTSP_FAIL:
                L.e("RTSP链接失败");
                break;
            case ConstantLive.GET_OSD_TIME_FAIL:
                L.e("获取OSD时间失败");
                break;
            case ConstantLive.SD_CARD_UN_USEABLE:
                L.e("SD卡不可用");
                break;
            case ConstantLive.SD_CARD_SIZE_NOT_ENOUGH:
                L.e("SD卡空间不足");
                break;
            case ConstantLive.CAPTURE_FAILED_NPLAY_STATE:
                L.e("非播放状态不能抓拍");
                break;
        }
    }

}




















